﻿using System;
using System.Text;
using System.Drawing;
using System.Buffers;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.InteropServices;

public static partial class gl
{
    private static Random rnd = new Random();

    public unsafe delegate double delegatefunc_xa_n(double* xa, int n);
    public static delegatefunc_xa_n f_xa_n { get; set; }

    public unsafe delegate double delegatefunc_xa_nj(double* xa, int n, int j);
    public static delegatefunc_xa_nj f_xa_nj { get; set; }

    public unsafe delegate double delegatefunc_xa_ya_n(double* xa, double* ya, int n);
    public static delegatefunc_xa_ya_n f_xa_ya_n { get; set; }

    public unsafe delegate double delegatefunc_xa_ya_mn(double* xa, double* ya, int m, int n);
    public static delegatefunc_xa_ya_mn f_xa_ya_mn { get; set; }
    public static delegatefunc_xa_ya_mn s_xa_ya_mn { get; set; }

    public unsafe delegate void delegatefunc_xa(double* x);
    public static delegatefunc_xa f_xa { get; set; }

    public delegate double delegatefunc_x(double x);
    public static delegatefunc_x f_x = null;
    public static delegatefunc_x df_x = null;

    public delegate double delegatefunc_xy(double x, double y);
    public static delegatefunc_xy f_xy { get; set; }

    public unsafe delegate void delegatefunc_x_ya(double x, double* y);
    public static delegatefunc_x_ya s_x_ya { get; set; }

    public unsafe delegate void delegatefunc_x_ya_n_da(double x, double* y, int n, double* d);
    public static delegatefunc_x_ya_n_da f_x_ya_n_da { get; set; }
    public static delegatefunc_x_ya_n_da ss_x_ya_n_da { get; set; }

    public unsafe delegate void delegatefunc_abcd(double a, double* b, double* c, double* d);
    public static delegatefunc_abcd f_abcd { get; set; }

    public delegate double delegatefunc_abc(double a, double b, double c);
    public static delegatefunc_abc f_abc { get; set; }

    public unsafe delegate double delegatefunc_nm_xa_ya_ua_va(int n, int m, double* x, double* y, double* u, double* v);
    public static delegatefunc_nm_xa_ya_ua_va s_nm_xa_ya_ua_va { get; set; }

    /// <summary>
    /// == 0.0
    /// </summary>
    /// <param name="v"></param>
    /// <returns></returns>
    public static bool EQ0(double v)
    {
        return Math.Abs(v) <= float.Epsilon;
    }

    /// <summary>
    /// != 0.0
    /// </summary>
    /// <param name="v"></param>
    /// <returns></returns>
    public static bool NE0(double v)
    {
        return Math.Abs(v) > float.Epsilon;
    }

    /// <summary>
    /// == 1.0
    /// </summary>
    /// <param name="v"></param>
    /// <returns></returns>
    public static bool EQ1(double v)
    {
        return Math.Abs(v - 1.0) <= float.Epsilon;
    }

    /// <summary>
    /// != 1.0
    /// </summary>
    /// <param name="v"></param>
    /// <returns></returns>
    public static bool NE1(double v)
    {
        return Math.Abs(v - 1.0) > float.Epsilon;
    }

    /// <summary>
    /// 一维数组转二维数组
    /// </summary>
    /// <param name="a"></param>
    /// <param name="yn"></param>
    /// <param name="xn"></param>
    /// <returns></returns>
    public static double[,] array_1_to_2(double[] a, int yn, int xn)
    {
        xn = a.Length / yn;
        double[,] rs = new double[yn, xn];
        for (int y = 0; y < yn; y++)
        {
            for (int x = 0; x < xn; x++)
            {
                rs[y, x] = a[y * xn + x];
            }
        }
        return rs;
    }

    /// <summary>
    /// 二维数组转一维数组
    /// </summary>
    /// <param name="a"></param>
    /// <returns></returns>
    public static double[] array_2_to_1(double[,] a)
    {
        double[] rs = new double[a.GetLength(0) * a.GetLength(1)];
        int idx = 0;
        for (int y = 0; y < a.GetLength(0); y++)
        {
            for (int x = 0; x < a.GetLength(1); x++)
            {
                rs[idx++] = a[y, x];
            }
        }
        return rs;
    }

    /// <summary>
    /// 一维数组转二维数组
    /// </summary>
    /// <param name="a"></param>
    /// <param name="yn"></param>
    /// <param name="xn"></param>
    /// <returns></returns>
    public static int[,] array_1_to_2(int[] a, int yn, int xn)
    {
        xn = a.Length / yn;
        int[,] rs = new int[yn, xn];
        for (int y = 0; y < yn; y++)
        {
            for (int x = 0; x < xn; x++)
            {
                rs[y, x] = a[y * xn + x];
            }
        }
        return rs;
    }

    /// <summary>
    /// 二维数组转一维数组
    /// </summary>
    /// <param name="a"></param>
    /// <returns></returns>
    public static int[] array_2_to_1(int[,] a)
    {
        int[] rs = new int[a.GetLength(0) * a.GetLength(1)];
        int idx = 0;
        for (int y = 0; y < a.GetLength(0); y++)
        {
            for (int x = 0; x < a.GetLength(1); x++)
            {
                rs[idx++] = a[y, x];
            }
        }
        return rs;
    }

    public static string html_table(string title, double[] a)
    {
        double[,] aa = array_1_to_2(a, a.Length, 1);
        return html_table(title, aa);
    }

    /// <summary>
    /// HTML显示表格
    /// </summary>
    /// <param name="a"></param>
    /// <returns></returns>
    public static string html_table(string title, double[,] a)
    {
        StringBuilder sb = new StringBuilder();
        if (title.Length > 0)
            sb.AppendLine("<h3>" + title + "</h3>");
        sb.AppendLine("<style>");
        sb.AppendLine("table { border-collapse:collapse; } ");
        sb.AppendLine("td { padding-left:15px;padding-top:10px;padding-right:15px;padding-bottom:10px;white-space:nowrap; } ");
        sb.AppendLine("td.c { text-align:center;min-width:40px; } ");
        sb.AppendLine("td.r { text-align:right;min-width:40px; } ");
        sb.AppendLine("tr.h { background-color:#FAFAFF;font-weight:bold;text-align:center; } ");
        sb.AppendLine("td.h { background-color:#FAFAFF;font-weight:bold;text-align:center;min-width:40px; } ");
        sb.AppendLine("</style>");

        sb.AppendLine("<table width='0%' border=1 bordercolor='#EAEAEE;' style=''>");

        if (a.GetLength(1) > 1)
        {
            sb.Append("<tr class='h'>");
            sb.Append("<td></td>");
            for (int x = 0; x < a.GetLength(1); x++)
            {
                sb.Append($"<td class='c'>{x}</td>");
            }
            sb.AppendLine("</tr>");
        }

        for (int y = 0; y < a.GetLength(0); y++)
        {
            sb.Append("<tr>");
            sb.Append($"<td class='h'>{y}</td>");
            for (int x = 0; x < a.GetLength(1); x++)
            {
                sb.Append($"<td class='r'>{a[y, x]}</td>");
                /*
                if (Math.Abs(a[y, x]) < 1.0E-11)
                {
                    sb.Append($"<td class='r'>0</td>");
                }
                else if (Math.Abs(a[y, x]) < 1000.0 && Math.Abs(a[y, x]) >= 1.0E-11)
                {
                    if (Math.Abs(a[y, x] - (int)a[y, x]) < 1.0E-8)
                        sb.Append($"<td class='r'>{(int)(a[y, x])}</td>");
                    else
                        sb.Append($"<td class='r'>{String.Format("{0:F12}", a[y, x])}</td>");
                }
                else
                {
                    sb.Append($"<td class='r'>{String.Format("{0:E12}", a[y, x])}</td>");
                }
                */
            }
            sb.AppendLine("</tr>");
        }
        if (a.GetLength(1) > 1)
        {
            sb.Append("<tr class='h'>");
            sb.Append("<td></td>");
            for (int x = 0; x < a.GetLength(1); x++)
            {
                sb.Append($"<td class='c'>{x}</td>");
            }
            sb.AppendLine("</tr>");
        }

        sb.AppendLine("</table>");
        sb.AppendLine("<br>");

        return sb.ToString();
    }

    public static string html_table(string title, int[] a)
    {
        double[] aa = new double[a.Length];
        for (int i = 0; i < aa.Length; i++) aa[i] = a[i];
        return html_table(title, aa);
    }
}

